package com.zhangc.blog.admin.web.handler;

import java.text.MessageFormat;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.ValidationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.NoSuchMessageException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.ModelAndView;

import com.zhangc.blog.base.BlogServiceExceptionFactory;
import com.zhangc.blog.base.MessageSourceUtils;
import com.zhangc.blog.base.ResultBO;
import com.zhangc.blog.base.constants.CommonConstants;
import com.zhangc.blog.base.validator.ServiceException;

/**
 * 功能描述:<br>
 *
 * @author wx:fdzhangc
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@RestControllerAdvice
public class RestControllerExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(RestControllerExceptionHandler.class);
    @Autowired
    MessageSourceUtils messageSourceUtils;
    @Autowired
    BlogServiceExceptionFactory blogServiceExceptionFactory;

    @ExceptionHandler({ Throwable.class })
    public Object handleException(HttpServletRequest request, HttpServletResponse response, Throwable ex) throws Throwable {
        //HttpServletRequest request = HttpServletUtil.getRequest();
        boolean ajaxRequest = isAjaxRequest(request);
        if (ajaxRequest) {
            ServiceException se = this.wrapServiceException(ex);
            return ResultBO.error(null, se.getCode(), se.getMessage());
        } else {
            //            if (code.equals("xxx") ||  code.equals("xxxx")) {
            //                //跳转到全局错误处理，没有权限访问页面，403页面
            //                return new ModelAndView("redirect:/403");
            //            } else if (code.equals(PermissionExceptionEnum.URL_NOT_EXIST.getCode())) {
            //                //跳转到全局错误处理，路径不存在，404页面
            //                return new ModelAndView("redirect:/404");
            //            } else {
            //                //跳转到全局错误处理，服务器异常，500页面
            //                return new ModelAndView("redirect:/500");
            //            }
            return new ModelAndView("redirect:/500");
        }

    }

    protected ServiceException parseServiceException(Throwable e) throws Throwable {
        ServiceException se;
        if (e instanceof ServiceException) {
            se = (ServiceException) e;
        } else if (e instanceof ValidationException) {
            se = ServiceException.INVALID_PARAMETER;
        } else if (e instanceof BindException) {
            se = ServiceException.INVALID_PARAMETER;
        } else if (e instanceof MethodArgumentNotValidException) {
            se = ServiceException.INVALID_PARAMETER;
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            se = ServiceException.INVALID_PARAMETER;
        } else {
            //se = (ServiceException) e;
            //不是能处理的异常，再次抛出
            throw e;
        }

        return se;
    }

    private ServiceException createServiceException(ServiceException se) {
        String code = this.getCode(se);
        String message = this.getMessage(se);
        ServiceException exception = blogServiceExceptionFactory.create(code, message);
        exception.setStackTrace(se.getStackTrace());
        return exception;
    }

    protected String getMessage(ServiceException se) {
        boolean i18nEnabled = blogServiceExceptionFactory.isI18nEnabled();
        if (i18nEnabled) {
            try {
                return messageSourceUtils.getMessage(se.getName(), se.getArgs(), Locale.CHINA);
            } catch (NoSuchMessageException var4) {
                logger.warn("错误信息国际化键值没配置： {}", var4.getMessage());
                return se.getName();
            }
        } else {
            return MessageFormat.format(se.getMessage(), se.getArgs());
        }
    }

    protected String getCode(ServiceException se) {
        boolean i18nEnabled = blogServiceExceptionFactory.isI18nEnabled();
        if (i18nEnabled) {
            try {
                return messageSourceUtils.getMessage(se.getName(), (Object[]) null, Locale.ROOT);
            } catch (NoSuchMessageException var4) {
                logger.warn("错误编码国际化键值没配置： {}", var4.getMessage());
                return se.getName();
            }
        } else {
            return se.getCode();
        }
    }

    public ServiceException wrapServiceException(Throwable e) throws Throwable {
        ServiceException se = this.parseServiceException(e);
        ServiceException exception = this.createServiceException(se);
        if (se == ServiceException.UNKNOWN) {
            logger.error("【系统异常】", e);
        } else if (se == ServiceException.INVALID_PARAMETER) {
            logger.error("【参数异常】", e);
        } else {
            logger.error("【业务异常】", exception);
        }

        return exception;
    }

    public static boolean isAjaxRequest(HttpServletRequest request) {
        return !"GET".equalsIgnoreCase(request.getMethod()) ||
                request.getHeader(CommonConstants.ACCEPT).contains("application/json");
    }

}
